package com.yjt.common.security;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;

import org.apache.commons.codec.binary.Base64;

/**
 * 利用RSA算法进行数字签名、验签工具类
 * 
 * @author hqy 2013-8-21
 * @version 01.00
 */
public class SignUtil {
	private final static String DEFAUL_STRING_ENCODING = "utf-8";

	private SignUtil() {
	}

	/**
	 * 使用私钥对原始数据进行签名
	 * 
	 * @param sourceData
	 *            需要签名的原始数据
	 * @param privateKey
	 *            用于签名的私钥
	 * @return 签名后的数据，以Base64编码格式返回
	 * @throws Exception
	 */
	public static String sign(String sourceData, PrivateKey privateKey)
			throws Exception {
		byte[] sourceBytes = sourceData.getBytes(DEFAUL_STRING_ENCODING);
		// 签名
		byte[] signBytes = sign(sourceBytes, privateKey);
		// 签名后的数据进行Base64编码
		byte[] encodeByte = Base64.encodeBase64(signBytes);
		String signString = new String(encodeByte, DEFAUL_STRING_ENCODING);
		return signString;
	}

	/**
	 * 使用私钥对原始数据进行签名
	 * 
	 * @param sourceData
	 *            需要签名的原始数据
	 * @param privateKey
	 *            用于签名的私钥
	 * @return 签名后的数据
	 * @throws Exception
	 */
	public static byte[] sign(byte[] sourceData, PrivateKey privateKey)
			throws Exception {
		/**
		 * 可选RSA签名算法：MD2withRSA、MD5withRSA、SHA1withRSA、SHA256withRSA、
		 * SHA384withRSA、SHA512withRSA
		 */
		// 获取签名算法对象Signature
		Signature sign = Signature.getInstance("SHA1withRSA");
		// 初始化签署签名的私钥
		sign.initSign(privateKey);
		// 更新要签名的数据（字节）
		sign.update(sourceData);
		// 返回对原始数据签名后的字节
		byte[] signDate = sign.sign();

		return signDate;
	}

	/**
	 * 使用公钥对传入的原始数据和签名数据进行验签
	 * 
	 * @param sourceData
	 *            原始数据
	 * @param signData
	 *            签名后的数据(Base64编码格式)
	 * @param publicKey
	 *            用于验签的公钥
	 * @return 如果签名得到验证，则返回 true，否则将返回 false
	 * @throws Exception
	 */
	public static boolean verify(String sourceData, String signData,
			PublicKey publicKey) throws Exception {
		byte[] sourceBytes = sourceData.getBytes(DEFAUL_STRING_ENCODING);

		byte[] signBytes = signData.getBytes(DEFAUL_STRING_ENCODING);
		// 以Base64编码格式还原需要检验的签名后的数据
		byte[] realSignBytes = Base64.decodeBase64(signBytes);

		return verify(sourceBytes, realSignBytes, publicKey);
	}

	/**
	 * 使用公钥对传入的原始数据和签名数据进行验签
	 * 
	 * @param sourceData
	 *            原始数据
	 * @param signData
	 *            签名后的数据
	 * @param publicKey
	 *            用于验签的公钥
	 * @return 如果签名得到验证，则返回 true，否则将返回 false
	 * @throws Exception
	 */
	public static boolean verify(byte[] sourceData, byte[] signData,
			PublicKey publicKey) throws Exception {
		/**
		 * 可选RSA签名算法：MD2withRSA、MD5withRSA、SHA1withRSA、SHA256withRSA、
		 * SHA384withRSA、SHA512withRSA
		 */
		// 获取签名算法对象Signature
		Signature verify = Signature.getInstance("SHA1withRSA");
		// 初始化验证签名的公钥
		verify.initVerify(publicKey);
		// 更新要验证的数据（字节）
		verify.update(sourceData);
		// 验证传入的签名数据是否合法
		boolean isVerifySucess = verify.verify(signData);

		return isVerifySucess;
	}
}
